﻿/**
 * @fileOverview 浏览器判别工具
 * 
 * @version qinglan_Browser 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 浏览器信息
 * 
 * @namespace
 * @type Object
 */
qinglan.Browser = qinglan.Browser || {};
/**
 * 是否为IE浏览器
 * 
 * @public
 * @field
 * @return {Boolean} 是否为IE浏览器
 */
qinglan.Browser.isIE = !!document.all;
﻿/**
 * @fileOverview 类扩展
 * 
 * @version qinglan_extend 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};

/**
 * 扩展类命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Extend = qinglan.Extend || {};
/**
 * 简单的进行函数扩展
 * 
 * @param {Object}
 *            target 目标对象,需要扩展的对象
 * @param {Object}
 *            prototypes 扩展对象
 * @param {Boolean}
 *            isStatic 是否使用静态方式进行扩展
 * @return {Object} 扩展好的target
 * @function
 * @static
 * @public
 */
qinglan.Extend.simple = function(target, prototypes, isStatic) {
	for (var i in prototypes) {
		(isStatic == true || isStatic == 1) ? target[i] = prototypes[i] : (!target.prototype && (target.prototype ={}) && (target.prototype[i] = prototypes[i]));
	}
	return target;
};
﻿// @include "Array.js"
// @include "Argument.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 命名空间实现工具
 * 
 * @version qinglan_Object 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 命名空间实现类
 * 
 * @type Object
 */
qinglan.Namespace = qinglan.Namespace || {};
/**
 * 进行命名空间分割
 * 
 * @param {String}
 *            nameSpace 命名空间以'.'分割
 * @return {Object} ns：命名空间分割数组, len : 命名空间分割长度
 */
qinglan.Namespace._parseNamespace = function(nameSpace) {
	var nsArray = nameSpace.split('.');
	return {
		ns : nsArray,
		len : nsArray.length
	};
};
/**
 * 创建命名空间,如果没有指定上下文,默认是window
 * 
 * @param {String}
 *            nameSpace 命名空间以'.'分割
 * @param {Object}
 *            context 上下文
 * @param {Boolean}
 *            ismanual 是否手动完成最后对象初始化
 */
qinglan.Namespace.create = function(nameSpace, context, ismanual) {
	context = context || window;
	var nsObj = qinglan.Namespace._parseNamespace(nameSpace);
	var nsLast = qinglan.Array.getTheLast(nsObj.ns);
	for (var i = 0; i < nsObj.len - 1; i++) {
		context[nsObj.ns[i]] = context[nsObj.ns[i]] || {};
		context = context[nsObj.ns[i]] || {};
	}
	if (!ismanual) {
		!context[nsLast] && (context[nsLast] = {});
		context = context[nsLast];
	}
	return {
		instance : context,
		key : nsLast
	};
};
/**
 * 得到命名空间所指向的对象<br/> 当然,这里有更快的实现方式,用eval(nameSpace)即可,但是eval是高危函数,所以采取了这种方法
 * 
 * @param {String}
 *            nameSpace 命名空间以'.'分割
 * @param {Object}
 *            context 上下文,默认是window
 * @return {Object} 命名空间指向的对象
 */
qinglan.Namespace.get = function(nameSpace, context) {
	context = context || window;
	var nsObj = qinglan.Namespace._parseNamespace(nameSpace);
	for (var i = 0; i < nsObj.len; i++) {
		context[nsObj.ns[i]] = context[nsObj.ns[i]] || null;
		if (context[nsObj.ns[i]] == null) {
			qinglan.Debug.error('The nameSpace : [' + nameSpace
					+ '] is not definded!!');
			return null;
		};
		context = context[nsObj.ns[i]] || {};
	}
	return context;
};
/**
 * 创建命名空间数组<br/> 根据传进来的arguments创建命名空间字串
 * 
 * @param {String}
 *            arguments 方法参数
 * 
 * @return {String} 命名空间字串
 */
qinglan.Namespace.generate = function() {
	var nsArray = [];
	qinglan.Array.each(qinglan.Argument.toArray(arguments), function(value) {
				nsArray.push(value);
			});
	return nsArray.join('.');
};
﻿// @include "Namespace.js"
// @include "Typs.js"
// @include "Extend.js"
// @include "Function.js"
// @include "Argument.js"
// @include "Object.js"
/**
 * @fileOverview 模块引入工具
 * 
 * @version qinglan_Module 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 模块引入工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Module = qinglan.Module || {};

/**
 * 存放模块信息
 * 
 * @type Object
 */
qinglan.Module.cache = {
	ReqModules : {},
	DefaultDelayTime : 10,
	LoadingScripts : {},
	LoadingModules : {},
	LoadedScripts : {},
	LoadedModules : {}
};
/**
 * 创建模块
 * @param {String} name 模块名字
 * @param {String}{Array} urls 模块自身js
 * @param {Object} opt 设置参数
 * @return {qinglan.Module.createModule} 模块
 */
qinglan.Module.createModule = function(name,urls,opt){
	this.name = name;
	/**
	 * 本模块引用js
	 * @field
	 */
	this.urls = [];
	/**
	 * 依赖模块
	 * @field
	 */
	this.requirements = [];
	/**
	 * 加载参数设置
	 * @field
	 */
	this.opt = qinglan.Extend.simple({isAsyn:true,delay:qinglan.Module.cache.DefaultDelayTime},opt,1);

	/**
	 * 注册依赖模块
	 * @param {String}{Array} 依赖模块
	 * @function
	 */
	this.require = function(moduleLIst){
		var args = qinglan.Argument.toArray(arguments);
		qinglan.Object.each(args,function(param){
			qinglan.Type.isArray(param) ? qinglan.Object.each(param,function(p){
				this.requirements.push({'name' : p});
			},this) : this.requirements.push({'name' : param});
		},this);
	};

	qinglan.Type.isArray(urls) ? this.urls = urls : 	this.urls.push(urls);
	
	return this;
};

/**
 * 注册模块
 * @param {String} name 模块名字
 * @param {String}{Array} urls 模块自身js
 * @param {Object} opt 设置参数
 * @param {Boolean} rewrite 进行模块重写
 * @return {qinglan.Module.createModule} 模块对象
 */
qinglan.Module.register = function(name,urls,opt,rewrite){
	var ReqModules = qinglan.Module.cache.ReqModules;
	var module = new qinglan.Module.createModule(name,urls,opt);
	if(ReqModules[module.name]){
		rewrite ? (ReqModules[module.name] = module && qinglan.Debug.info('Module : ['+module.name+'] will be Overwritten!')) : qinglan.Debug.info('Module : ['+module.name+']  was already registered!');
	}else{
		ReqModules[module.name] = module;
		qinglan.Debug.info('Module : ['+module.name+']  was registered!');
	}
	return module;
};
/**
 * 加载模块
 * 
 * @param {qinglan.Module.createModule} module 模块对象
 * @param {Function} callback 回调函数
 */
qinglan.Module.loadModule = function(module,callback){
	var Module = qinglan.Module;
	var loadScript = Module.cache.LoadedScripts;
	var loadingScript = Module.cache.LoadingScripts;
	var totalLoadLen = module.urls.length;
	var finishCount = 0;
	
	var checkScriptLoad = function(){
		var falg = true;
		qinglan.Object.each(module.urls,function(url){
			if(!loadScript[url]){falg = false;}
		});
		return falg;
	};

	var defaultCallback = function(url,flag){
		qinglan.Debug.info('Script : ['+url+'] was loaded ' + (flag ? 'success' : 'failed'))+'!';
		loadScript[url] = flag;
		delete loadingScript[url];
		finishCount++;
		if(finishCount == totalLoadLen && callback) {
			 callback(module.name,checkScriptLoad());
		}
		return false;
	};
 
	qinglan.Object.each(module.urls,function(url){
		if(!loadScript[url] && !loadingScript[url]){
			loadingScript[url] = true;
			module.opt.isAsyn ? Module._asynLoadScript(module.name,url,module.opt.delay,defaultCallback) :  Module._xhrLoadScrip(module.name,url,defaultCallback) ;
		}else{
			qinglan.Debug.info('Script : ['+url+'] was already ' + (loadingScript[url] ? 'loading' : 'loaded'))+'!';
		}
	});
};
/**
 * 使用xhr加载js
 * @param {String} moduleName 模块名字
 * @param {String} url 加载js的路径 
 * @param {Function} callback 回调队列
 */
qinglan.Module._xhrLoadScript = function(moduleName,url,callback){
	var xhr;
    if (window.XMLHttpRequest)
		xhr = new XMLHttpRequest();
	else if (window.ActiveXObject) {
		xhr = new ActiveXObject("Microsoft.XMLHTTP"); 
	}
	xhr.onreadystatechange = function(){
		if(xhr.readyState == 4){
			if( xhr.status == 200){
				qinglan.Module._injectScript(xhr.responseText,moduleName);
				qinglan.Module.cache.LoadedScripts[url] = true;
				callback && callback(url,true);
			}else if(xhr.status >= 400){
				callback && callback(url,false);
			}
		}
	};
    xhr.open("GET", url, true);
    xhr.send(null);
};
/**
 * 使用scriptTag加载js
 * @param {String} moduleName 模块名字
 * @param {String} url 加载js的路径
 * @param {Number} delay 延迟的时间
 * @param {Function} callback 回调队列
 */
qinglan.Module._asynLoadScript = function(moduleName,url,delay,callback){
	var scriptNode = qinglan.Module._createScriptNode(moduleName);
	scriptNode.onload= scriptNode.onreadystatechange = function(){
		if ((!scriptNode.readyState) || scriptNode.readyState == "loaded" || scriptNode.readyState == "complete" || scriptNode.readyState == 4 && scriptNode.status == 200) {
			callback && callback(url,true);	     	
	    }
	    return false;
	};
	scriptNode.onerror = function(){
		callback && callback(url,false);
		return false;
	};
	scriptNode.setAttribute('src',url);
	document.getElementsByTagName("head")[0].appendChild(scriptNode);
};

/**
 * 创建script标签
 * @param {String} scriptName 节点名字
 * @return {Element} script节点
 */
qinglan.Module._createScriptNode = function(scriptName) {
    var scriptNode = document.createElement("script");
    scriptNode.setAttribute("type", "text/javascript");
    scriptNode.setAttribute("language", "Javascript");
    try {
        scriptNode.setAttribute("name", scriptName);
    } catch (err) { }
    return scriptNode;    
};
/**
 * 将请求得到js插入到dom中
 * @param {String} scriptText 
 * @param {String} scriptName
 */
qinglan.Module._injectScript = function (scriptText, scriptName) {
    var scriptNode = qinglan.Module._createScriptNode(scriptName);
    scriptNode.text = scriptText;
    document.getElementsByTagName("head")[0].appendChild(scriptNode);
};
/**
 * 模块主函数
 * @param {String}{Array} moduleName 要使用的模块的名字
 * @param {Function} callback 加载模块之后的回调函数
 * @param {Object} context 回调绑定对象
 * @return {}
 * 
 * @function
 * @private
 * 
 */
qinglan.Module.use= function(moduleName, callback, context){
	var Module = qinglan.Module;
	var module = Module.cache.ReqModules[moduleName];
	var loadModule = Module.cache.LoadedModules;
	var loadingModule = Module.cache.LoadingModules;
	var totalLen = module.requirements.length;
	var finishCount = 0;
	
	if(!module){
		qinglan.Debug.error('Module : ['+moduleName+'] was not registered!!');
		callback && callback(moduleName,false);
		return false;
	}
	if(loadModule[moduleName] || loadingModule[moduleName]){//如果已经加载了就不用再加载咯
		qinglan.Debug.info('Module : ['+moduleName+'] was already'+(loadingModule[moduleName] ? ' loading ' : ' loaded ')+ ' !!');
		callback && callback(moduleName,true);
		return true;		
	}
	
	var checkModuel = function(){
		var flag = true;
		qinglan.Object.each(module.requirements,function(reqModule){
			if(!Module.cache.LoadedModules[reqModule.name]){flag = false;}	
		});
		return flag;
	};
	
	var doLoadModule = function (cb,context){
		loadingModule[moduleName] = true;
		Module.loadModule(module,function(name,flag){
				qinglan.Debug.info('Module : ['+name+'] was loaded ' + (flag ? 'success' : 'failed'))+'!';
				loadModule[moduleName] = flag;
				delete loadingModule[moduleName];
				cb && cb.call(context,checkModuel());
			});
	};
	
	var defaultCallback = function(reqModuleName,flag){
		finishCount++;
		if(finishCount == totalLen){
			doLoadModule(callback,context);
		}
		return false;
	};
	
	totalLen == 0 ? doLoadModule(callback,context) : qinglan.Object.each(module.requirements,function(reqModule){
		qinglan.Module.use(reqModule.name,defaultCallback,context);
	});
	
};

﻿/**
 * @fileOverview 基础工具类
 * 
 * @version qinglan_util 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 基础工具类
 * 
 * @namespace
 * @type Object
 */
qinglan.Util = qinglan.Util || {};
﻿// @include "../code/Type.js"
/**
 * @fileOverview 模版类
 * 
 * @version qinglan_tmpl 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 模版命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Tmpl = qinglan.Tmpl || {};
/**
 * 进行简单的字符串模版替换<br/> 主要使用正则进行参数的匹配和替换<br/> 模版中需要替换的数据名称和obj中的一致并且用'{'和'}'括起来<br/>
 * 另外,如果模版中有的数据obj中没有则默认为空('')
 * 
 * @param {String}
 *            str 需要替换的模版
 * @param {Object}
 *            obj 模版数据来源
 * @return {String} 生成后的具体数据
 */
qinglan.Tmpl.smTmpl = function(str, obj) {
	if (!qinglan.Type.isString(str)) {
		return '';
	}
	if (!(qinglan.Type.isObject(obj) && 'isPrototypeOf' in obj)) {
		return str;
	}
	return str.replace(/\{([^{}]+)\}/g, function(match, key) {
				var value = obj[key];
				return (value !== undefined) ? '' + value : '';
			});
};
﻿/**
 * @fileOverview 字符串工具类
 * 
 * @version qinglan_string 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 基础工具类
 * 
 * @namespace
 * @type Object
 */
qinglan.String = qinglan.String || {};
/**
 * 去除字符串两边的空白
 * 
 * @param {String}
 *            str 字符串
 * @return {String} 去除两变空白的字串
 */
qinglan.String.trim = function(str) {
	return str.replace(/(^\s*)|(\s*$)/g, '');
};
﻿/**
 * @fileOverview 参数扩展工具
 * 
 * @version qinglan_argument 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 参数扩展命名空间
 * 
 * @type Object
 */
qinglan.Argument = qinglan.Argument || {};
/**
 * 把方法参数转换为数组
 * 
 * @param {Object}
 *            args 方法参数
 * @param {Number}
 *            num 截取参数索引
 * @return {Object}{Array} arguments的数组形式
 */
qinglan.Argument.toArray = function(args, num) {
	return Array.prototype.slice.call(args, num || 0);
};
﻿// @include "Browser.js"
// @include "Type.js"
// @include "Array.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 基础对象类
 * 
 * @version qinglan_Object 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 基础工具类
 * 
 * @namespace
 * @type Object
 */
qinglan.Object = qinglan.Object || {};
/**
 * 将对象转换为json字串
 * 
 * @param {Object}
 *            obj 对象
 * @return {String} 转换后的字符串
 */
qinglan.Object.toJsonString = function(obj) {
	if (qinglan.Type.isString(obj)) {
		qinglan.Debug.info('The typeof obj : [' + obj + '] is String');
		return obj.toString();
	}
	if (qinglan.Type.isUndefined(obj)) {
		return 'undefined';
	}
	if (qinglan.Type.isNull(obj)) {
		return 'null';
	}
	if (qinglan.Type.isObject(obj)) {
		var result = [];
		if (qinglan.Type.isArray(obj)) {
			for (var i = 0; i < obj.length; i++)
				result.push(qinglan.Object.toJsonString(obj[i]));
			result = "[" + result.join() + "]";
		} else {
			for (var i in obj)
				result.push("\"" + i + "\":"
						+ qinglan.Object.toJsonString(obj[i]));
			result = "{" + result.join() + "}";
		}
		return result;
	} else {
		return obj.toString();
	}
};
/**
 * Each 方法
 * 
 * @param {Object} obj 需要被遍历的对象
 * @param {Function} fun 遍历的时候执行的方法
 * @param {Object} context 执行上下文
 * 
 * @function
 * @public
 */
qinglan.Object.each = function(obj,fun,context){
	if(qinglan.Type.isArray(obj)){
		qinglan.Array.each(obj,fun,context);
	}else{
		for (var index in obj){
			fun.call(context,obj[index],index,obj);
		}
	}
};
﻿// @include "Namespace.js"
// @include "Typs.js"
// @include "Extend.js"
// @include "Function.js"
// @include "Argument.js"
/**
 * @fileOverview 类声明
 * 
 * @version qinglan_Class 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 类工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Class = qinglan.Class || {};
/**
 * 创建一个类<br/> 可以独立使用
 * 
 * @param {Object}
 *            baseClass 基类
 * @param {Object}
 *            extend 扩展类
 * @param {Boolean}
 *            staticMethod 是否使用静态方法扩展
 * @return {Object} 扩展后的类
 * @function
 * @static
 * @public
 */
qinglan.Class.create = function(baseClass, extend, staticMethod) {
	var klass = baseClass ? baseClass.extend({}, true) : function() {
	};
	var ext = extend || {};
	if (baseClass) {
		klass = baseClass.extend({}, true);
	} else {
		klass = function() {
		};
		klass.extend = function(ext, createNewClass) {
			var target = this;
			if (createNewClass) {
				target = arguments.callee.call(function() {
						}, this.prototype);
				target.extend = this.extend;
				target.create = this.create;
			}
			for (var i in ext) {
				target.prototype[i] = ext[i];
			}
			return target;
		};
		klass.create = ext.init || function() {
			return new this();
		};
	}
	if (staticMethod) {
		for (var i in ext) {
			klass[i] = ext[i];
		}
	} else {
		klass.extend(ext);
	}
	return klass;
};
/**
 * 创建模块应用
 * 
 * @param {String}
 *            nameSpace 命名空间
 * @param {Object}{Function}
 *            prototype 对象的类成员属性
 * @param {Object}
 *            staticMod 对象的静态类方法
 * @param {Object}
 *            context 上下文 所生命的命名空间将会挂在这个上下文里面,默认是window
 * @return {Object} 模块的类
 * @function
 * @static
 * @public
 */
qinglan.Class.mode = function(nameSpace, prototypes, staticMod, context) {
	/**
	 * 得到prototype的对象
	 */
	function firePrototype(proto) {
		return qinglan.Type.isFunction(proto) ? proto.call() : proto;
	}

	// 扩展默认的constructor和init函数
	prototypes = firePrototype(prototypes);
	prototypes = qinglan.Extend.simple({
				constructor : qinglan.Function.emptyFun,
				init : qinglan.Function.emptyFun
			}, prototypes, 1);

	var ns = qinglan.Namespace.create(nameSpace, context,true);
	!ns.instance[ns.key] && (ns.instance[ns.key] = {});
	!ns.instance[ns.key]._constructor
			&& (ns.instance[ns.key]._constructor = prototypes.constructor);
	!ns.instance[ns.key]._init && (ns.instance[ns.key]._init = prototypes.init);
	delete prototypes.constructor;
	delete prototypes.init;
	ns.instance[ns.key] = (function(self) {
		var that = self;
		function _init() {
			that._constructor.apply(this, arguments);
			that._init.apply(this, arguments);
		}
		return function() {
			_init.apply(this, arguments);
		};
	})(ns.instance[ns.key]);
	qinglan.Extend.simple(ns.instance[ns.key], prototypes, false);
	qinglan.Extend.simple(ns.instance[ns.key], firePrototype(staticMod), true);
	return ns.instance[ns.key];
};
// @include "../code/Browser.js"
// @include "../code/Type.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 页面节点操作工具
 * 
 * @version qinglan_dom 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 页面节点操作节点命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Math = qinglan.Math || {};
/**
 * 根据随机数范围产生随机数
 * 
 * @param {Number}
 *            start 随机数下限
 * @param {Number}
 *            end 随机数上限
 * @param {Boolean}
 *            isInt 是否为整数
 * @return {Number} 产生的随机数
 */
qinglan.Math.random = function(start, end, isInt) {
	if (isInt) {
		return Math.floor(Math.random(end - start) + start);
	} else {
		return (Math.random(end - start) + start);
	}
};
﻿// @include "Type.js"
/**
 * @fileOverview 基础扩展类
 * 
 * @version qinglan_Array 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 数组工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Array = qinglan.Array || {};
/**
 * 遍历数组的方法
 * 
 * @param {Array}
 *            array 数组
 * @param {Function}
 *            fun 对每个元素执行的方法,将会把当前处理到的元素作为参数传给这个function
 * @param {Object}
 *            context 方法的上下文
 */
qinglan.Array.each = function(array, fun, context) {
	if (qinglan.Type.isFunction(array.forEach)) {
		array.forEach(fun, context);
	} else {
		if (qinglan.Type.isArray(array)) {
			for (var i = 0, len = array.length; i < len; i++) {
				fun.call(context, array[i], i, array);
			}
		}
	}
};
/**
 * 判断数组是否有某个元素
 * 
 * @param {Array}
 *            array 数组
 * @param {Object}
 *            item 需要检查的对象
 */
qinglan.Array.has = function(array, item) {
	for (var i = 0, len = array.length; i < len; i++) {
		if (array[i] == item)
			return true;
	}
	return false;
};
/**
 * 从数组里面移除某个元素,如果有重复的话,会全部移除
 * 
 * @param {Array}
 *            array 数组
 * @param {Object}
 *            item 需要移除的对象
 */
qinglan.Array.remove = function(array, item) {
	var j = array.length;
	for (var i = 0; i < j; i++) {
		if (array[i] == item) {
			array.splice(i, 1);
			j--;
		}
	}
};
/**
 * 获取数组最大值或最小值
 * 
 * @param {Array}
 *            array 数组 PS:需要是能转换为比较大小的数组
 * @param {String}
 *            type 获取值的方式,最大为max,最小为min
 */
qinglan.Array.getExtreme = function(array, type) {
	var result = 0;
	for (var i = 0, j = this.length; i < j; i++) {
		(type == 'max' || type == 1) ? (array[i] * 1 > result)
				&& (result = array[i] * 1) : (array[i] * 1 < result)
				&& (result = array[i] * 1);
	}
	return result;
};

/**
 * 将两个元素交换
 * 
 * @param {Array}{Object}
 *            array 数组
 * @param {Number}{String}
 *            first 第一个下标
 * @param {Number}{String}
 *            second 第二个下标
 * @return {Object}{Array} 交换后的数组
 */
qinglan.Array.swap = function(array, first, second) {
	var temp = array[first];
	array[first] = array[second];
	array[second] = temp;
	return array;
};
/**
 * 将数组打乱,原理是随机交换两个元素的值,可以设定洗牌次数
 * 
 * 
 * @param {Array}
 *            array 数组
 * @param {number}
 *            times 洗牌次数,如果不存在就按数组长度计算
 */
qinglan.Array.random = function(array, times) {
	var len = array.length, index_1, index_2;
	times = times || len;
	for (var i = 0; i < times; i++) {
		index_1 = Math.floor(Math.random() * len);
		while ((index_2 = Math.floor(Math.random() * len)) == index_1) {
			continue;
		}
		qinglan.Array.swap(array, index_1, index_2);
	}
	return array;
};
/**
 * 从数组里面计算有多少个指定的对象
 * 
 * @param {Array}
 *            array 数组
 * @param {Object}
 *            item 需要计算的对象
 * @return {Number} 计算值
 */
qinglan.Array.count = function(array, item) {
	var count = 0;
	for (var i = 0, len = array.length; i < len; i++) {
		if (array[i] == item) {
			count++;
		}
	};
	return count;
};
/**
 * 得到数组最后一个元素
 * 
 * @param {Array}
 *            array 数组
 * @return {Object} array数组最后一个元素
 */
qinglan.Array.getTheLast = function(array) {
	return array[array.length - 1];
};
// @include "../extend/Debug.js"
/**
 * @fileOverview 事件通知扩展工具
 * 
 * @version qinglan_listener 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 事件通知类，在对象内部把事件抛出
 * 
 * @param {Srting}
 *            name 本事件实例名字(ID)
 * @param {Object}
 *            target 事件触发对象
 */
qinglan.Listener = function(name, target) {
	this.name = name ? name : qinglan.Listener.index++;
	this.target = target;
	this.advicePool = {};
	
	qinglan.Listener._pool[name] = this;
};
/**
 * 监听器索引
 * 
 * @type Number
 */
qinglan.Listener._index = 0; 
/**
 * 所有事件对象缓存索引
 * 
 * @type Object
 */
qinglan.Listener._pool = {};
/**
 * 根据名字得到事件对象实例
 * 
 * @param {String}
 *            name 实例名字
 * @return {qinglan.Listener} 事件对象实例
 */
qinglan.Listener.getListenerByName = function(name) {
	return qinglan.Listener._pool[name];
};
/**
 * 增加监听的函数
 * 
 * @param {String}
 *            type 事件类型
 * @param {String}
 *            name 监听器名字
 * @param {Function}
 *            advice 监听器
 */
qinglan.Listener.prototype.addAdvice = function(type, name, advice) {
	!this.advicePool[type] && (this.advicePool[type] = []);
	var event = function() {
		advice.apply(this.target || window, arguments);
	};
	this.advicePool[type][name] = event;
};
/**
 * 删除监听函数
 * 
 * @param {String}
 *            type 事件类型
 * @param {String}
 *            name 监听器名字
 */
qinglan.Listener.prototype.removeAdvice = function(type, name) {
	try {
		delete this.advicePool[type][name];
	} catch (e) {
		qinglan.Debug.error('Delete Advice : [' + advice + '] from Listener : [' + this + '] error !');
	}
};
/**
 * 通知所有制定类型的监听器
 * 
 * @param {String}
 *            type 事件类型
 * @param {Array}
 *            args 参数数组
 */
qinglan.Listener.prototype.notify = function(type, args) {
	if (this.advicePool[type]) {
		for (var name in this.advicePool[type]) {
			this.advicePool[type][name].apply(this, args);
		}
	}
};
﻿// @include "Browser.js"
// @include "Type.js"
// @include "Argument.js"
/**
 * @fileOverview Function扩展工具
 * 
 * @version qinglan_function 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * Function扩展命名空间
 * 
 * @type Object
 */
qinglan.Function = qinglan.Function || {};
/**
 * 进行方法绑定
 * 
 * @param {Object}
 *            obj 绑定的对象
 * @param {Function}
 *            fun 绑定的方法
 * @return {Object} 可执行对象
 */
qinglan.Function.bind = function(obj, fun) {
	return function() {
		qinglan.Type.isString(fun) && (fun = obj[fun]);
		!qinglan.Type.isFunction(fun) && (fun = qinglan.Function.emptyFun);
		return fun.apply(obj, qinglan.Argument.toArray(arguments, 2));
	};
};
/**
 * 空的方法
 * 
 * @static
 * @type Function
 */
qinglan.Function.emptyFun = function() {
};

/**
 * 方法反射<br/>
 * 根据tag得到方法的相应部分内容
 * <ul>
 * 		<li><b>body</b> : 方法体</li>
 * 		<li><b>param</b> : 方法参数</li>
 * 		<li><b>name</b> : 方法名字 但是对匿名方法无效</li>
 * 		<li><b>scope</b> : 方法调用链</li>
 *		<li><b>anonymous</b> : 匿名方法方法字串</li>
 * </ul>
 * 
 * @param {Function} fun 方法
 * @param {String} tag 获取反射类型
 * @type Function
 * @public
 * @see http://www.cnblogs.com/rubylouvre/archive/2011/05/30/2062953.html author司徒正美
 */
qinglan.Function.reflect=function(fun,tag){
	if(qinglan.Type.isFunction(fun)){
		var _r_function = /^function\b\s*([\$\S]*)\s*\(/;//得到方法名
		var _r_codebody = /[^{]*\{([\d\D]*)\}$/;//得到方法体
		var _r_params = /[^\(]*\(([^\)]*)\)[\d\D]*/;//得到方法参数
		tag = (tag || 'body').toLowerCase();
		with (func.toString()) {
			return (tag == 'body') ? replace(_r_codebody, '$1').replace(/^\s*|\s*$/g, '')
			: (tag == 'param') ? ((tag=replace(_r_params, '$1')) ? tag.split(/[,\s]+/) : [])
			: (tag == 'name') ? match(_r_function)[1]
			: (tag == 'scope') ? '[function (' +arguments.callee(func, 'param')+ ') {\n' +arguments.callee(func, 'body')+ '\n}][0]'
			: (tag == 'anonymous') ? Function.apply(this, arguments.callee(func, 'param').concat(arguments.callee(func, 'body')))
			: 'Block() with bad arguments.';
		};
	}
};
/**
 * 得到非匿名方法的名字
 * 
 * @public
 * @param {Function} fun 方法
 * @return {String} 方法名字
 */
qinglan.Function.getName=function(fun){
	if(qinglan.Type.isFunction(fun)){
		return fun.name || String(f).match(/^function\s*([^)]*)\(/)[1];
	}
};
﻿// @include "Browser.js"
/**
 * @fileOverview 类型判断类<br/> 本类使用
 *               javascript神秘花园提供的Object.prototype.toString.call方法进行强类型检测
 * 
 * @version qinglan_Type 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 类型工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Type = qinglan.Type || {};
/**
 * 判断对象是否为此类型<br/> *
 * 
 * @public
 * @static
 * @see 请参考 javascript神秘花园 <br/> 
 * 		<p style="color : #FFAA3E"> http://bonsaiden.github.com/JavaScript-Garden/zh/#types.typeof </p>
 * @param {String}
 *            type
 * @param {Object}
 *            obj
 * @return {Boolean}
 */
qinglan.Type.is = function(type, obj) {
	var klass = Object.prototype.toString.call(obj).slice(8, -1);
	return obj !== undefined && obj !== null && klass === type;
};
/**
 * 判断对象类型是否为数字
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为数字
 */
qinglan.Type.isNumber = function(obj) {
	return qinglan.Type.is('Number', obj);
};

/**
 * 判断对象类型是否为字符串
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为字符串
 */
qinglan.Type.isString = function(obj) {
	return qinglan.Type.is('String', obj);
};

/**
 * 判断对象类型是否为布尔值
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为布尔值
 */
qinglan.Type.isBoolean = function(obj) {
	return qinglan.Type.is('Boolean', obj);
};
/**
 * 判断对象类型是否为Date对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Date对象
 */
qinglan.Type.isDate = function(obj) {
	return qinglan.Type.is('Date', obj);
};
/**
 * 判断对象类型是否为Array对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Array对象
 */
qinglan.Type.isArray = function(obj) {
	return qinglan.Type.is('Array', obj);
};
/**
 * 判断对象类型是否为Function对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Function对象
 */
qinglan.Type.isFunction = function(obj) {
	return qinglan.Type.is('Function', obj);
};

/**
 * 判断对象类型是否为RegExp对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为RegExp对象
 */
qinglan.Type.isRegExp = function(obj) {
	return qinglan.Type.is('RegExp', obj);
};

/**
 * 判断对象类型是否为Object对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Object对象
 */
qinglan.Type.isObject = function(obj) {
	return qinglan.Type.is('Object', obj);
};

/**
 * 判断对象类型是否为Error对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Error对象
 */
qinglan.Type.isError = function(obj) {
	return qinglan.Type.is('Error', obj);
};
/**
 * 判断对象是否定义
 * 
 * @deprecated
 * @public
 * @static
 * @param {Object}
 *            varName 需要判断的对象
 * @return {Boolean} 是否定义
 */
qinglan.Type.isDefined = function(varName) {
	// 抛出 ReferenceError 异常
	return typeof varName !== 'undefined';
};

/**
 * 判断对象是否元素节点
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否定义
 */
qinglan.Type.isElement = function(obj) {
	return !!(obj && obj.nodeType == 1);
};
/**
 * 判断对象类型是否为Null对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Null对象
 */
qinglan.Type.isNull = function(obj) {
	if (qinglan.Browser && qinglan.Browser.isIE) {
		return obj === null;
	}
	return qinglan.Type.is('Null', obj);
};
/**
 * 判断对象类型是否为Undefined对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Undefined对象
 */
qinglan.Type.isUndefined = function(obj) {
	if (qinglan.Browser && qinglan.Browser.isIE) {
		return obj === undefined;
	}
	return qinglan.Type.is('Undefined', obj);
};
﻿// @include "../code/Function.js"
/**
 * @fileOverview 终端记录类<br/> 本类使用console完成记录工作
 * 
 * @version qinglan_Debug 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 类型工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Debug = qinglan.Debug || {};
/**
 * debug初始化函数<br/> 为了在debug模式下ie不报错，重新覆盖window.console对象<br/>
 * 本函数会在加载本文件的时候自动运行
 * 
 * @static
 * @private
 * @type Function
 */
qinglan.Debug.init = (function() {
	if (!window.console) {
		window.console = {};
		var methods = ["log", "debug", "info", "warn", "error", "assert",
				"dir", "dirxml", "group", "groupEnd", "time", "timeEnd",
				"count", "trace", "profile", "profileEnd"];
		for (var i = 0, method; method = methods[i++];)
			window.console[method] = qinglan.Function.emptyFun();
	}
	return true;
})();
/**
 * 是否处于debug调试模式<br/> 在调试模式下会输出调试提示信息
 * 
 * @type Boolean
 */
qinglan.Debug.debugMode = true;
/**
 * 进行log输出
 * 
 * @private
 * @function
 * @param {String}
 *            logger console中的logger类型
 * @param {Object}
 *            args 需要进行log的参数
 */
qinglan.Debug._logger = function(logger, args) {
	if(!qinglan.Debug.debugMode){return ;}
	try {
		console[logger].apply(console, args);
	} catch (e) {
		// workaround for IE9
		try {
			for (var i = 0, arr = []; i < args.length; i++) {
				arr.push(args[i]);
			}
			console[logger](arr.join(' '));
		} catch (e) {
			// opera in old version 
			if (window.opera && opera.postError) {
				opera.postError.call(null,args);
			}
		}
	}
};
/**
 * 进行info类型的log
 * 
 * @public
 * @function
 */
qinglan.Debug.info = function() {
	qinglan.Debug._logger('info', arguments);
};
/**
 * 进行error类型的log
 * 
 * @public
 * @function
 */
qinglan.Debug.error = function() {
	qinglan.Debug._logger('error', arguments);
};
/**
 * 记录断言错误
 * 
 * @public
 * @function
 */
qinglan.Debug.assert = function(expr, text) {
	if (!expr) {
		qinglan.Debug._logger('error', 'assertion failed!', text);
		throw new Error('assertion failed! ' + text);
	}
};
﻿// @include "code/Browser.js"
// @include "code/Type.js"
// @include "extend/Debug.js"
/**
 * @fileOverview 异步加载工具
 * 
 * @version qinglan_Import 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 异步加载js组件
 * 
 * @type Object
 */
qinglan.Import = qinglan.Import || {};
/**
 * 加载js文件
 * 
 * @param {String}
 *            src js文件请求地址
 * @param {Function}
 *            callback 回调函数
 * @param {Object}
 *            param 回调函数参数
 * 
 */
qinglan.Import.js = function(src, callback, param) {
	var d = document;
	var scriptTag = document.createElement("script");
	scriptTag.src = src;
	d.body.appendChild(scriptTag);
	if (qinglan.Type.isUndefined(callback)) {
		scriptTag.onload = function() {
			try {
				callback.call(window, param);
			} catch (e) {
				qinglan.Debug.error('Load js file : [ ' + src + ' ]faild ');
			}
		};
		scriptTag.onreadystatechange = function() {
			if (this.readyState == "complete" || this.readyState == "loaded") {
				try {
					callback.call(window, param);
				} catch (e) {
					qinglan.Debug.error('Load js file : [ ' + src + ' ]faild ');
				}
			}
		};
	}
};
/**
 * 引入css文件
 * 
 * @param {String}
 *            src css文件请求地址
 */
qinglan.Import.css = function(src) {
	var node = document.createElement("link");
	node.rel = "stylesheet";
	node.type = "text/css";
	node.href = src;
	document.getElementsByTagName("head")[0].appendChild(node);
};
/**
 * 引入图片文件
 * 
 * @param {String}
 *            src 图片地址
 * @param {Function}
 *            callback
 * @return {Image} 图片对象
 */
qinglan.Import.img = function(src, callback) {
	var img = new Image();
	img.onload = function() {
		callback.call(img);
		this.onload = null;
	};
	img.src = src;
	return img;
};
﻿// @include "code/Browser.js"
// @include "code/Type.js"
// @include "extend/Debug.js"
// @include "code/Array.js"
/**
 * @fileOverview dom文档onready函数工具
 * 
 * @version qinglan_onready 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};

/**
 * dom加载完后即执行fun
 * 
 * @param {Function}
 *            fun 需要在domOnready时候执行的方法
 * @type function
 */
qinglan.onReady = function(fun) {
	if (qinglan.Type.isFunction(fun)) {
		qinglan.onReady._loadingFun.push(fun);
	} else {
		qinglan.Debug.error('The Object :[' + fun + '] is not a Function!!');
		return false;
	}
	if (qinglan.onReady._firstTime) {
		qinglan.onReady._firstTime = false;
		if (!qinglan.Browser.isIE) {
			document.addEventListener('DOMContentLoaded', function() {
						qinglan.onReady._fireFun();
					}, false);
			return false;
		}
		// 尝试检测document.doScroll是否可以用
		(function() {
			try {
				document.documentElement.doScroll('left');
			} catch (e) {
				qinglan.onReady._timeout = setTimeout(arguments.callee, 0);
				return false;
			}
			qinglan.onReady._fireFun();
			clearTimeout(qinglan.onReady._timeout);
		})();
		//
		document.onreadystatechange = function() {
			if (document.readyState == 'complete') {
				document.onreadystatechange = null;
				qinglan.onReady._fireFun();
			}
		};
		return false;
	}

};
/**
 * 是否dom加载完成
 * 
 * @private
 * @field
 * @type Boolean
 */
qinglan.onReady.isReady = false;
/**
 * 需要dom加载完成时候调用的函数
 * 
 * @private
 * @field
 * @type Array
 */
qinglan.onReady._loadingFun = new Array();
/**
 * timeout缓存对象
 * 
 * @private
 * @field
 * @type Object
 */
qinglan.onReady._timeout = null;
/**
 * 是否第一次进入onready绑定时间
 * 
 * @private
 * @field
 * @type Object
 */
qinglan.onReady._firstTime = true;
/**
 * 进行事件调用
 */
qinglan.onReady._fireFun = function() {
	qinglan.onReady.isReady = true;
	qinglan.Array.each(qinglan.onReady._loadingFun, function(fun) {
				fun.call(window);
			}, window);
	qinglan.onReady._loadingFun = new Array();
};
